package at.pp.match3.activity;

import java.util.Random;

import org.anddev.andengine.engine.Engine;
import org.anddev.andengine.engine.camera.Camera;
import org.anddev.andengine.engine.options.EngineOptions;
import org.anddev.andengine.engine.options.EngineOptions.ScreenOrientation;
import org.anddev.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;
import org.anddev.andengine.entity.modifier.MoveModifier;
import org.anddev.andengine.entity.scene.Scene;
import org.anddev.andengine.entity.scene.background.ColorBackground;
import org.anddev.andengine.entity.sprite.TiledSprite;
import org.anddev.andengine.entity.util.FPSLogger;
import org.anddev.andengine.opengl.texture.Texture;
import org.anddev.andengine.opengl.texture.TextureOptions;
import org.anddev.andengine.opengl.texture.region.TextureRegionFactory;
import org.anddev.andengine.opengl.texture.region.TiledTextureRegion;
import org.anddev.andengine.ui.activity.BaseGameActivity;

import android.util.DisplayMetrics;
import at.pp.match3.activity.listener.IEntityModifierListenerImplementation;
import at.pp.match3.activity.listener.ISpriteSelectionListener;
import at.pp.match3.sprite.GameButton;
import at.pp.match3.util.LOG;

public class StartActivity extends BaseGameActivity implements
        ISpriteSelectionListener {

    public static int CAMERA_WIDTH = 480;
    public static int CAMERA_HEIGHT = 320;

    private static final int GRID_HEIGHT = 6;
    private static final int GRID_WIDTH = 4;

    private Camera mCamera;
    private Texture mTexture;
    private TiledTextureRegion mRedButtomTextureRegion;
    public TiledSprite ball;
    public Random random;
    private Scene scene;
    private boolean isSpriteSelected;
    public boolean isMoving;
    public GameButton selectedSprite;
    private GameButton[][] grid;
    GameButton movingSprite;

    @Override
    public Engine onLoadEngine() {
        random = new Random();

        DisplayMetrics dm = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(dm);

        CAMERA_WIDTH = dm.widthPixels;
        CAMERA_HEIGHT = dm.heightPixels;

        LOG.log("camera height: " + CAMERA_HEIGHT);
        LOG.log("camera width: " + CAMERA_WIDTH);
        LOG.log("density: " + dm.density);

        // / dm.density
        mCamera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);

        return new Engine(new EngineOptions(true, ScreenOrientation.PORTRAIT,
                new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT),
                this.mCamera));
    }

    @Override
    public void onLoadResources() {
        this.mTexture = new Texture(128, 256,
                TextureOptions.BILINEAR_PREMULTIPLYALPHA);
        this.mRedButtomTextureRegion = TextureRegionFactory
                .createTiledFromAsset(this.mTexture, this, "gfx/dot_red3.png",
                        0, 0, 2, 5);

        this.mEngine.getTextureManager().loadTexture(this.mTexture);
    }

    @Override
    public Scene onLoadScene() {
        this.mEngine.registerUpdateHandler(new FPSLogger());

        scene = new Scene(1);
        scene.setBackground(new ColorBackground(0, 0, 0.8784f));

        final int centerX = (CAMERA_WIDTH - this.mRedButtomTextureRegion
                .getWidth()) / 2;
        final int centerY = (CAMERA_HEIGHT - this.mRedButtomTextureRegion
                .getHeight()) / 2;

        final TiledSprite ball = new TiledSprite(centerX, centerY,
                this.mRedButtomTextureRegion);

        grid = new GameButton[GRID_WIDTH][GRID_HEIGHT];
        for (int i = 0; i < GRID_HEIGHT; i++) {
            for (int j = 0; j < GRID_WIDTH; j++) {
                GameButton gameButton = new GameButton(j * ball.getWidth(), i
                        * ball.getHeight(), i, j,
                        this.mRedButtomTextureRegion.clone(), this);
                gameButton.setColor(random.nextInt(5));
                this.grid[j][i] = gameButton;
                scene.getLastChild().attachChild(gameButton);
                scene.registerTouchArea(gameButton);
            }
        }

        this.ball = ball;
        scene.getLastChild().attachChild(ball);
        scene.setTouchAreaBindingEnabled(true);

        return scene;
    }

    @Override
    public void onLoadComplete() {
        ball.registerEntityModifier(new MoveModifier(3, ball.getX(), random
                .nextInt(CAMERA_WIDTH), ball.getY(), random
                .nextInt(CAMERA_HEIGHT),
                new IEntityModifierListenerImplementation(this)));
    }

    @Override
    public boolean onSpriteSelected(GameButton sprite) {
        scene.setBackground(new ColorBackground(random.nextFloat(), random
                .nextFloat(), random.nextFloat()));

        if (isMoving) {
            return true;
        }

        // select new sprite
        if (!this.isSpriteSelected) {
            selectSprite(sprite);
            return true;
        }

        // one sprite already selected -> initiate movement
        if (this.isSpriteSelected) {
            if (selectedSprite.isExchangable(sprite)) {
                LOG.log("START MOVEMENT");
                selectedSprite.setUnselectedTile();
                startMovement(sprite, true, false);
                return true;
            } else if (selectedSprite.equals(sprite)) {
                deselectSprite(sprite);
                return true;
            } else {
                selectedSprite.setUnselectedTile();
                selectSprite(sprite);
                return true;
            }
        }

        // deselect sprite
        if (selectedSprite != null && sprite.isSelected) {
            deselectSprite(sprite);
            return true;
        }

        return true;
    }

    private void startMovement(GameButton sprite, boolean checkMatch,
            boolean isReversing) {
        sprite.registerEntityModifier(new MoveModifier(1, sprite.getX(),
                selectedSprite.getX(), sprite.getY(), selectedSprite.getY(),
                new ExchangeCompletedDetector(this, checkMatch, isReversing)));
        selectedSprite.registerEntityModifier(new MoveModifier(1,
                selectedSprite.getX(), sprite.getX(), selectedSprite.getY(),
                sprite.getY(), new ExchangeCompletedDetector(this, false,
                        isReversing)));
        isMoving = true;
        movingSprite = sprite;
    }

    public void deselectSprite(GameButton sprite) {
        this.isSpriteSelected = false;
        sprite.isSelected = false;
        selectedSprite = null;
        sprite.setUnselectedTile();
    }

    public void selectSprite(GameButton sprite) {
        this.isSpriteSelected = true;
        sprite.isSelected = true;
        selectedSprite = sprite;
        sprite.setSelectedTile();
    }

    public void updateGrid() {
        if (selectedSprite != null && movingSprite != null) {
            int tempX = selectedSprite.gridPositionX;
            int tempY = selectedSprite.gridPositionY;

            selectedSprite.gridPositionX = movingSprite.gridPositionX;
            selectedSprite.gridPositionY = movingSprite.gridPositionY;

            movingSprite.gridPositionX = tempX;
            movingSprite.gridPositionY = tempY;
        }

    }

    public void reversetMovement() {
        startMovement(movingSprite, true, true);
    }
}
